参数：Param  ObjNumber
变量：Var
属性：Attr
'''
# 1. 创建模型
m = Model("mip")

# 2.设置参数&变量
x = m.addVars(lb=0 ,ub=10,vtype=GRB.BINARY, name="x")

# 3.设置目标函数
m.setObjective(2*x, GRB.MAXIMIZE)

# 4.设置约束
m.addConstr(x>=1, "c0")

# 如果要写进lp文件阅读，可以：
m.update()
m.write("mip.lp")

# 如果要从lp格式中读出模型
m = read("mip.lp")

# 5.求解
m.optimize() '''





''' addVar ( lb=0.0, ub=GRB.INFINITY, obj=0.0, vtype=GRB.CONTINUOUS, name=" ", column=None )一次增加一个变量 '''
# addVar()
# lb (可自行选择设置): 决策变量下界
# ub (可自行选择设置): 决策变量上界
# obj (可自行选择设置): 决策变量在目标函数中的因子系数
# vtype (可自行选择设置): 决策变量类型，包括GRB.CONTINUOUS， GRB.BINARY， GRB.INTEGER，GRB.SEMICONT，GRB.SEMIINT
# name (可自行选择设置): 变量名
# column (可自行选择设置): Column object that indicates the set of constraints in which the new variable participates, and the associated coefficients.

'''从变量的名称中检索变量。如果多个变量有相同的名称，则此方法选择任意一个。如果没有变量具有该名称，则返回null。'''
#print(model.getVarByName('shanshan'))  就是addVar(,name='shanshan')

'''addVars() 一次增加多个变量  MODEL.addVars(20, 8, vtype=gurobipy.GRB.BINARY)     设置了变量Cij   i∈[0,20) j∈[0,8)'''


# for v in m.getVars():
#         print('%s %g' % (v.varName, v.x))

        #v.后面的varName(以%s输出)对应变量名x，y，z,记住是addvars(,name='变量名')
        #v.后面的x(%g输出)也属于变量的属性，对应变量的最后优化后的取值
        # %g : 把输出的值按照 %e(指数)或者 %f(浮点数)类型中输出长度较小的方式输出'''





'''Variable type == Vtype(变量类型)'''
# 'C' for continuous      (GRB.CONTINUOUS) : 连续变量可以取指定的下界(lb)和上界(ub)之间的任何值
# 'B' for binary          (GRB.BINARY)     : 只能取0和1
# 'I' for integer         (GRB.INTEGER)    : 整数变量可以在指定的下界(lb)和上界(ub)之间取任何整数值
# 'S' for semi-continuous (GRB.SEMICONT)   : 半连续变量可以取指定的下界(lb)和上界(ub)之间的任何值，或者取0的值
# 'N' for semi-integer    (GRB.SEMIINT)    : 半整型变量可以取指定下界和上界之间的任何整数值，也可以取0的值。

'''non-convex非凸二次规划的处理策略'''
# 类型:int    默认值:-1     最小值:-1     最大值:2   设置处理非凸二次目标或非凸二次约束的策略
#    设置为0时，如果原始用户模型包含非凸二次结构，则会报告错误。
#    设置为1时，如果非凸二次结构在求解过程中不能被丢弃或线性化，则会报告一个错误。
#    设置为2时，将非凸二次型问题转化为双线性形式和应用空间分枝法求解。
#    默认的-1设置 当前相当于1，在将来的版本中可能会更改为相当于2


'''Model.printAttr() 打印一个或多个属性的值。  printAttr ( attrs, filter='*' )'''
# 如果attrs是一个约束或变量属性，则打印该属性的所有非零值，以及关联的约束或变量名称。
# 如果attrs是一个属性列表，则打印列出的所有属性的属性值。该方法接受一个可选的筛选参数，允许您选择要打印的特定属性值(通过对约束或变量名筛选)



# Example usage:
# setParam("Cuts", 2)     setParam("Heu*", 0.5)   setParam("*Interval", 10)

''' 广义的约束条件
m.addGenConstrMin(Z, [x1, x2, 5], name="z_min_in3")      z要是 x1 x2 5中的最小值
m.addGenConstrMax(Z, [x1, x2, 5], name="z_min_in3")
    转换为一般的约束条件
m.addConstr(z==min_([x1,x2,5]),"z_min")   要导入gurobipy的所有模块   from gurobipy import *
m.addConstr(z==max_([x1,x2,5]),"z_max")
'''
'''特殊约束表达式和使用'''
'''广义约束—Abs'''     #  返回绝对值   例如: x = |y|
                     # m.addGenConstrAbs(x, y, "absconstr")
                     # m.addConstr(x == abs_(y), "absconstr"")

'''·广义约束——And'''   #例如: x = 1且y =1,那么z=1，否则z= 0
                      # m.addGenConstrAnd(z, [x,y], "andconstr")
                      # m.addConstr(z == and_(x, y), "andconstr")

'''·广义约束—Or'''     #例如: x =0且y = 0,那么z= 0，否则z = 1
                     # m.addGenConstrOr(z,[x,y], "orconstr")
                     # m.addConstr(z == or_(x, y), "orconstr")

'''·广义约束—lndicator'''
#  addGenConstrlndicator(binvar, binval, lhs,sense, rhs, name)
#  binvar 指示变量   binval 指示变量的值 取{0,1}  指示变量的值为1的时候约束才成立，否则可以违反约束
#  lhs  约束左端项    rhs 约束右端项.
#  sense 约束符号    name 广义约束名称

# 例如:  如果z=1,则可以得到 x+y <= 4
# m.addGenConstrIndicator( z , True , x + y , GRB.LESS_EQUAL, 4, 'indicator')
# m.addConstr((z == 1)>>(x+ y<= 4))


'''·范围约束  addRange( expr, lower, upper, name) '''
#  expr表达式
#  lower下界 upper上界 name约束名称
# 例如:5<= x + y + z <= 10.
#  addRange(x+y+z,5,10,"c")            m.addConstr( x+y+z==[5,12] )





'''setObjective'''
# m.setObjective(expr, sense)    sense:优化方向 GRB.MAXIMIZE  和   GRB.MINIMIZE
'''如果只是要最优先的目标值'''
# print('Obj1: %g' % m.objVal)  # objVal：（优化后最优的目标结果值）


'''创建多目标函数(多个目标) setObjectiveN(expr, index, priority, weight, abstol, reltol, name)
各参数说明如下。'''
# (1)expr:目标函数表达式，如x+ 2y + 3z。
# (2)index:目标函数对应的序号(0,1,2,…),即第几个目标，注意目标函数序号应从0开始。
# (3)prority:优先级,为整数，值越大表示目标优先级越高。
# (4)weight:权重(浮点数)，在合成型多目标解法中使用该参数，表示不同目标之间的组合权重。
# (5)abstol:允许的目标函数值最大的降低量abstol(浮点数)，即当前迭代的值相比最优值的可接受劣化程度。
# (6)reltol:abstol的百分数表示，如rlol=0.05则表示可接受劣化程度是5%。
# (7)name:目标函数名称。
# 需要注意的是，在Gurobi的多目标优化中，要求所有的目标函数都是线性的，并且目标函数的优化方向应一致，即全部最大化或全部最小化，因此可以通过乘以-1实现不同的优化方向。
# 当前Gurobi支持3种多目标模式，分别是Blend（合成型)、Hierarchical(分层型)、两者的混合型。
'''Gurobi支持三种多目标模式:
Blend(合成型) 有权重(weight,说白了就是系数), 没有优先级(priorty)。'''
# 例如优化:obj1= x+y weight1 = 1  obj2 = x-5y   weight2 = -2
# Gurobi会混合这两个目标值形成: 1*(x+y) - 2*(x- 5y)= -x+11y 求最小值
# 例如   m.setObjectiveN( x+y, index=O, weight=1, name='obj1')
#       m.setObjectiveN( x-5y, index=1, weight=-2, name='obj2')

'''Hierarchical(分层型)无权重，有优先级(priority的值越大，越优先考虑)'''
# 例如优化: obj1 = x+y+3*z     priority = 10       m.setObjectiveN( x+y+3*z, index=O, priority=10, name='obj1')
#          obj2 = 2*x+y+3*z   priority = 5        m.setObjectiveN(2*x+y+3*z, index=1, priority=5, name='obj2')
# 按照优先级大小优化(先优化Obj1),若没有设定abstol或reltol,在优化低优先级目标时,不会改变高优先级的目标值。
# 假设Obj1=10,在优化obj2时只能在使得obj1=10的所有解中挑选最优解。
'''混合两种 Blend + Hierarchical'''
# m.setObjectiveN(x+y+3*z, index=O, weight=0.1,priority=1, name='obj1')
# m.setObjectiveN(2*x+y+3*z, index=1, weight=3, priority=3, name='obj2')



'''通过参数ObjNumber选择特定的目标,进而获得对应的目标函数值。'''
'''可以通过遍历NumObj属性查询(或修改)模型中的目标数量。'''
# print(m.NumObj) 输出结果为2 ，因为我们设置了两个目标函数, 序号 index=0 ,index=1

# for i in range(m.NumObj):     可以使用NumObj属性查询(或修改)模型中的目标数量，它的值是目标函数的数量。遍历它，得到的是一个个index的值
#     m.setParam(GRB.Param.ObjNumber, i)
#     print('Obj%d = ' % (i + 1), m.ObjNVal)

'''m.ObjNVal是设置的所有目标函数优化后的值'''  # 因为第一个目标函数的index=0 所以打印出来的时候需要i+1，后边也如此。
'''ObjNName 当模型有多个目标时，此属性用于查询或修改 objective n. 通过“ObjNumber”参数设置“n”。'''

'''setParam()  设置或修改参数的值'''
# setParam ( paramname, newvalue )
# 将参数的值设置为新值。请注意，存储在Python数据结构(列表、字典等)或用户类内部的现有模型不受影响。
# Arguments:
# paramname: 包含要修改的参数名称的字符串。名字可以包含“*”和“?””通配符。如果有多个参数匹配，则列出匹配的名称，不修改任何名称。注意，大小写被忽略。
# newvalue: 参数需要的新值，可以是'default'（表示参数应该被重置为其默认值）




'''·setPWLObj( var,x, y )  目标函数(分段线性目标) '''
# ·var指定变量的目标函数是分段线性
# ·x定义分段线性目标函数的点的横坐标值(非减序列)  · y定义分段线性目标函数的点的纵坐标值
# 对一些非线性模型，可以使用这一功能去线性逼近。






'''1.关键函数使用 Model(name='模型名')'''
# name是模型的名称, 返回值是一个model对象，初始情况下没有变量和约束条件
# 调用方式：model1 = Model()


'''2.Model.addVar(lb, ub, obj, vtype, name,column)'''
# lb是下限，ub是上限，obj是目标的优化系数，vtype是变量类型，name是变量的名称，column是变量参与的约束以及优化系数。
# 所有的参数都是可选的，不指定就是默认值
# 变量的类型有GRB.CONTINUOUS, GRB.BINARY, GRB.INTEGER, GRB.SEMICONT, or GRB.SEMIINT


'''3.Model.addConstr( lhs, sense=None, rhs=None, name="" )'''
# lhs是约束的右侧，rhs是约束的左侧，sense是约束的类型，有(GRB.LESS_EQUAL, GRB.EQUAL, or GRB.GREATER_EQUAL



'''4.Model.addConstrs( generator, name="" )'''
# generator是Python表达式。这种表达方式比 2 直观一点，返回值是tupledict类型的
# 例：
# model.addConstrs(x[i] + x[j] <= 1 for i in range(5) for j in range(5))
# model.addConstrs((x[i,j] == 0 for i in range(4) for j in range(4) if i != j), name=’c’)
# 注意：generator表达式只能由一个比较关系。


'''5.Model.update()'''
# 对修改了的模型进行更新
#
#
# 6.Model.setObjective(expr, sense)
# 设置模型的优化函数
# expr是优化目标表达式，sense是优化类型，优化类型有GRB.MINIMIZE和GRB.MAXIMIZE，如果省略sense可以使用ModelSense函数来指定优化的类型。
#
#
# 7.Model.write(filename)
# 将优化模型，解向量，基向量，起始向量或参数设置写入文件，文件的类型有.mps, .rew, .lp .rlp，也可以只保存的模型的一部分，详见refman
#
#
# 8.Model.getVars()
# 返回模型中的所有变量
# 更多复杂的使用方法参考fefman和examples
# '''


